﻿using Microsoft.Net.Http.Headers;

using System.Security.Claims;

namespace anydata.Extensions
{
    public static class HttpContextExtensions
    {
        public static Task Proxy(this HttpContext context, IServiceProvider provider)
        {
            foreach(var item in context.Request.Query)
            {
                if (item.Key.StartsWith("proxyUr"))
                {
                    return context.ProxyTo(item.Value.ToString(), 
                        provider.GetRequiredService<IHttpClientFactory>().CreateClient("ProxyClient"));
                }
            }
            context.Abort();
            return Task.CompletedTask;
        }
        public static Task ProxyTo(this HttpContext context, string uriString, HttpClient http)
        {
            var uri = new Uri(uriString);
            var request = context.Request.CreateProxyHttpRequest();
            request.Headers.Host = uri.Authority;
            request.RequestUri = uri;
            return new ProxyContext(context, request, http).Send();
        }

        private static HttpRequestMessage CreateProxyHttpRequest(this HttpRequest request)
        {
            var requestMessage = new HttpRequestMessage();

            if (request.ContentLength > 0 || request.Headers.ContainsKey("Transfer-Encoding"))
            {
                var streamContent = new StreamContent(request.Body);
                requestMessage.Content = streamContent;
            }

            foreach (var header in request.Headers)
            {
                if (header.Key.StartsWith("X-Forwarded-", StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                var headerName = header.Key;
                var value = header.Value;

                if (string.Equals(headerName, HeaderNames.Cookie, StringComparison.OrdinalIgnoreCase) && value.Count > 1)
                {
                    value = string.Join("; ", value);
                }

                if (value.Count == 1)
                {
                    string headerValue = value;
                    if (!requestMessage.Headers.TryAddWithoutValidation(headerName, headerValue))
                    {
                        requestMessage.Content?.Headers.TryAddWithoutValidation(headerName, headerValue);
                    }
                }
                else
                {
                    string[] headerValues = value;
                    if (!requestMessage.Headers.TryAddWithoutValidation(headerName, headerValues))
                    {
                        requestMessage.Content?.Headers.TryAddWithoutValidation(headerName, headerValues);
                    }
                }
            }
            requestMessage.Method = new HttpMethod(request.Method);
            return requestMessage;
        }
    }
}
